package net.sourceforge.p4eclipse.ui;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;

/**
 * Console is a view that displays the communication with the CVS server
 */
public class ConsoleView extends ViewPart
{
	public final static String ID = PerforceUIPlugin.ID +  ".ui.ConsoleView"; //$NON-NLS-1$

	private TextViewer viewer;
	private Action copyAction;
	private Action selectAllAction;
	private Action clearOutputAction;
	private IDocument document;
	private List ranges = new ArrayList();
	private int lastWrite = 0;


	// All instances of the console
	static Vector instances = new Vector();

	/**
	 * Console Constructor
	 */
	public ConsoleView()
	{
		instances.add(this);
		document = new Document();
	}

	/**
	 * Returns all instances of the console view
	 * 
	 * @return all instances of the console
	 */
	public static ConsoleView[] getInstances()
	{
		return (ConsoleView[]) instances.toArray(new ConsoleView[instances.size()]);
	}

	/**
	 * Create contributed actions
	 */
	protected void createActions()
	{
		copyAction = new Action("Console.copy")
		{
			public void run()
			{
				viewer.doOperation(viewer.COPY);
			}
		};
  
		selectAllAction = new Action("Console.selectAll")
		{
			public void run()
			{
				viewer.doOperation(viewer.SELECT_ALL);
			}
		};

		clearOutputAction = new Action("Console.clearOutput", 
		                               PerforceUIPlugin.getPlugin().getImageDescriptor(PerforceUIPlugin.IMG_CLEAR))
		{
			public void run()
			{
				clearOutput();
				lastWrite = 0;
				ranges.clear();
			}
		};

		MenuManager mgr = new MenuManager();
		mgr.setRemoveAllWhenShown(true);
		mgr.addMenuListener(new IMenuListener()
		{
			public void menuAboutToShow(IMenuManager mgr)
			{
				fillContextMenu(mgr);
			}
		});
		Menu menu = mgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);

		// Create the local tool bar
		IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager();
		tbm.add(clearOutputAction);
		tbm.update(false);
	}

	/**
	 * Append the given string to the console
	 * 
	 * @param message  the string to append
	 */
	public void append(final String message, final int type)
	{
		Display display = Display.getCurrent();
		if (display == null)
			display = Display.getDefault();
		
		final Color[] fg = new Color[] { new Color(display, new RGB(224,   0,   0)),
		                                 new Color(display, new RGB(  0,   0,   0)),
		                                 new Color(display, new RGB(  0,   0, 132)) };
		
		
		display.asyncExec(new Runnable()
		{
			public void run()
			{
				document.set(document.get() + message);
				if (message.length() > 0 && viewer != null)
					viewer.revealRange(document.get().length() - 1, 1);
				
				if (viewer != null)
				{					
					ranges.add(new StyleRange(lastWrite, message.length(), fg[type], null));
					viewer.getTextWidget().setStyleRanges((StyleRange[])ranges.toArray(new StyleRange[ranges.size()]));
				}
				
				lastWrite = document.get().length();
			}
		});
	}

	/**
	 * Append the given string to all consoles
	 * 
	 * @param message  the string to append
	 */
	public static void appendAll(String message, int type)
	{
		/*
		// Show the console
		try
		{
			IWorkbenchPage page = PerforceUIPlugin.getActivePage();
			if (page != null)
			{
				page.showView(CONSOLE_ID);
			}
		}		
		catch (PartInitException e)
		{
			PerforceUIPlugin.log(e.getStatus());
		}
		*/

		if (message.length() == 0)
			return;
		boolean appendCr = message.charAt(message.length() - 1) == '\n';
		ConsoleView[] consoles = ConsoleView.getInstances();
		for (int i = 0; i < consoles.length; i++)
		{
			if (appendCr)
				message += "\n";
				
			consoles[i].append(message, type);
		}
	}

	/**
	 * Clear the output of the console
	 */
	public void clearOutput()
	{
		document.set("");
	}

	/**
	 * Add the actions to the context menu
	 * 
	 * @param manager  the manager of the context menu
	 */
	protected void fillContextMenu(IMenuManager manager)
	{
		copyAction.setEnabled(viewer.canDoOperation(viewer.COPY));
		selectAllAction.setEnabled(viewer.canDoOperation(viewer.SELECT_ALL));
		manager.add(copyAction);
		manager.add(selectAllAction);
		manager.add(new Separator());
		manager.add(clearOutputAction);
	}

	/*
	 * @see WorkbenchPart#setFocus()
	 */
	public void setFocus()
	{
		viewer.getTextWidget().setFocus();
	}

	/*
	 * @see WorkbenchPart#createPartControl(Composite)
	 */
	public void createPartControl(Composite parent)
	{
		Composite composite = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));

		viewer = new TextViewer(composite, SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
		GridData data = new GridData(GridData.FILL_BOTH);
		viewer.setEditable(false);
		viewer.getControl().setLayoutData(data);
		viewer.setDocument(document);

		createActions();
	}

	/*
	 * @see WorkbenchPart#dispose
	 */
	public void dispose()
	{
		instances.remove(this);
		super.dispose();
	}
}